/*
 * StartListModel.java
 *
 * Created on 4. prosinec 2006, 15:03
 *
 */

package cz.results.winter6.model.slmodel;

import cz.results.winter6.io.IoConfig;
import cz.results.winter6.model.KategorieConfig;
import cz.results.winter6.model.KategorieConfigList;
import cz.results.winter6.model.StartSubjekt;
import cz.results.winter6.model.StartSubjektList;
import cz.results.winter6.model.StartovniCasConfig;
import cz.results.winter6.model.Zavod;
import cz.results.winter6.sestavy.XML2PDF;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
import org.apache.avalon.framework.ExceptionUtil;

public class StartListModel {
    
    private Zavod zavod;
    
    /** trida urcena pro praci s daty, tykajici se startovni listiny (resi bussines logiku startovni listiny).
     *  obsahuje napr.: nasazovani startovnich casu, sestaveni startovni listiny do pdf, atd. */
    public StartListModel() {
    }
    
    /** nasadi startovni casy vsem startovnim kategoriim zavodu - UPLNE VSEM */
    public void nasadStartovniCasy(){
        Iterator iterator = getZavod().getStartovniKategorieConfigMap().keySet().iterator();
        while(iterator.hasNext()){
            String nazevTypuStartovniKategorie = (String) iterator.next();
            nasadStartovniCasy();
        }
    }
    
    /** trida nasadi startovni casy kategoriim popsanym objektem KategorieConfigList, ktery se vyhleda v objektu
     *  Zavod pomoci parametru metody NazevTypuStartovniKategorie */
    public void nasadStartovniCasy(String nazevTypuStartovniKategorie){
        nasadStartovniCasy(getZavod().getStartovniKategorieConfigMap().get(nazevTypuStartovniKategorie));
    }
    
    /** nasadi startovni casy vsem startovnim kategoriim popsanym v kategorieConfigList
     * @param kategorieConfigList obsahuje konfiguracni udaje pro nasazeni startovnich casu prislusnym kategoriim */
    public void nasadStartovniCasy(KategorieConfigList kategorieConfigList){
        
        Iterator iterator = kategorieConfigList.iterator();
        while(iterator.hasNext()){
            KategorieConfig config=(KategorieConfig)iterator.next();
            nasadStartovniCasyKategorii(config,getZavod().getSl());
        }
    }
    
    /** nasadi startovni casy jedne kategorii, konfiguracni udaje, podle kterych se casy nasadi jsou popsany
     *  v KategorieConfig
     *  @param config udava konfiguracni udaje cas startu prvniho zavodnika, interval, atd... a take
     *                filtr podle ktereho jsou vybrany startovni subjekty, ktere patri do prislusne
     *                startovni kategorie
     *  @param sl list vsech startovnich subjektu, ktere se ucastni zavodu, z techto je vybrana
     *            na zaklade filtru ta cast, ktere se nasazuji startovni casy (=startovni kategorie)
     */
    public static void nasadStartovniCasyKategorii(KategorieConfig config, StartSubjektList sl){
        StartSubjektList slVyfiltrovany;
        
        Iterator iterator1 = config.getStartovniCasConfigList().iterator();
        while(iterator1.hasNext()){                                             //pres vsechny jizdy v kategorii
            StartovniCasConfig startovniCasConfig = (StartovniCasConfig) iterator1.next();
            
            int jizda = startovniCasConfig.getJizda();
            int interval = startovniCasConfig.getInterval();
            
            slVyfiltrovany = config.getFiltr().filtruj(sl);    //vyfiltruje sl podle startovniho filtru
            
            Collections.sort(slVyfiltrovany, new StartovniPoradiComparator(jizda));     //seradi StartSubjektList podle poradi
            
            Iterator iterator = slVyfiltrovany.iterator();
            int i=0;
            int pocetIntervalu = 1;
            
            while (iterator.hasNext()){                                               //pres vsechny startovni subjekty ve startovni kategorii
                StartSubjekt startSubjekt=(StartSubjekt)iterator.next();
                pocetIntervalu = startSubjekt.getJizdy().get(jizda).getPocetStartovnichIntervalu();
                startSubjekt.getJizdy().get(jizda).setCasStartu((Calendar)startovniCasConfig.getStartOd().clone());
                startSubjekt.getJizdy().get(jizda).getCasStartu().add(Calendar.SECOND,interval*pocetIntervalu*i++);
                
                if(!iterator.hasNext()){              //startovni cas posledniho zavodnika si zapamatuju jako st.cas posledniho v kategorii
                    startovniCasConfig.setStartDo((Calendar)startSubjekt.getJizdy().get(jizda).getCasStartu().clone());
                }
                
            }
        }
    }
    
    
    
    
    public void doStartovkaPdfZobraz(String nazevTypuStartovniKategorie){
        doStartovkaPdfZobraz("startovka", nazevTypuStartovniKategorie);
    }
    
    public void doStartovkaPdfZobraz(String filename, String nazevTypuStartovniKategorie){
        doStartovkaPdf(filename, nazevTypuStartovniKategorie);
        zobrazPDF(filename);
    }
    
    public void doStartovkaPdfZobraz(KategorieConfigList kategorieConfigList){
        doStartovkaPdfZobraz("startovka", kategorieConfigList);
    }
    
    public void doStartovkaPdfZobraz(String filename, KategorieConfigList kategorieConfigList){
        doStartovkaPdf(filename, kategorieConfigList);
        zobrazPDF(filename);
    }
    
    
    
    
    public void doStartovkaPdf(String nazevTypuStartovniKategorie){
        doStartovkaPdf("startovka", nazevTypuStartovniKategorie);
    }
    
    public void doStartovkaPdf(KategorieConfigList kategorieConfigList){
        doStartovkaPdf("startovka", kategorieConfigList);
    }
    
    public void doStartovkaPdf(String filename, KategorieConfigList kategorieConfigList){
        doStartovkaXmlFile(filename, kategorieConfigList);
        convertXML2PDF(filename, kategorieConfigList.getXslFilename());
    }
    
    public void doStartovkaPdf(String filename, String nazevTypuStartovniKategorie){
        doStartovkaXmlFile(filename, nazevTypuStartovniKategorie);
        convertXML2PDF(filename, getZavod().getKategorieConfigList(nazevTypuStartovniKategorie).getXslFilename());
    }
    
    
    /** udela pdf jedne kategorie a zobrazi ho */
    public void doStartovkaPdfZobraz(KategorieConfigList kategorieConfigList, KategorieConfig kategorieConfig){
        doStartovkaPdfZobraz("startovka", kategorieConfigList, kategorieConfig);
    }
    
    /** udela pdf jedne kategorie a zobrazi ho */
    public void doStartovkaPdfZobraz(String filename, KategorieConfigList kategorieConfigList, KategorieConfig kategorieConfig){
        doStartovkaPdf(filename, kategorieConfigList, kategorieConfig);
        zobrazPDF(filename);
    }
   
    /** udela pdf jedny kategorie */
    public void doStartovkaPdf(KategorieConfigList kategorieConfigList, KategorieConfig kategorieConfig){
        doStartovkaPdf("startovka", kategorieConfigList, kategorieConfig);
    }
    
    /** udela pdf jedny kategorie */
    public void doStartovkaPdf(String filename, KategorieConfigList kategorieConfigList, KategorieConfig kategorieConfig){
        doStartovkaXmlFileKategorie(filename, kategorieConfigList, kategorieConfig);
        convertXML2PDF(filename, kategorieConfigList.getXslFilename());
    }
    
    /** podle indexu (vlastne typ stastovni listiny) vybere prislusnou konfiguraci kategorii a sestavi pro ne xml
     *  soubor se startovni listinou
     *  @param index udava vlastne typ startovni listiny, ktere kategorie, jak patri do startovni listiny */
    public void doStartovkaXmlFile(String nazevTypuStartovniKategorie){
        doStartovkaXmlFile("startovka", nazevTypuStartovniKategorie);
    }
    
    /** podle indexu (vlastne typ stastovni listiny) vybere prislusnou konfiguraci kategorii a sestavi pro ne xml
     *  soubor se startovni listinou
     *  @param xmlFilename jmeno vystupniho xml souboru bez cesty (IoConfig.datapath) a bez extenze
     *  @param index udava vlastne typ startovni listiny, ktere kategorie, jak patri do startovni listiny */
    public void doStartovkaXmlFile(String xmlFilename, String nazevTypuStartovniKategorie){
        doStartovkaXmlFile(xmlFilename, getZavod().getKategorieConfigList(nazevTypuStartovniKategorie));
    }
    
    
    /** udela xml soubor (xmlFilename) se startovkou pro vsechny kategorie obsazene v KategorieConfigList
     *  @param xmlFilename nazev souboru bez cesty (IoConfig.dataPath) a bez extenze (.xml)
     *  @param kategorieConfigList konfigurace startovnich kategorii */
    public void doStartovkaXmlFile(String xmlFilename, KategorieConfigList kategorieConfigList){
        try {
            BufferedWriter out= new BufferedWriter(new FileWriter(IoConfig.dataPath+xmlFilename+".xml"));
            out.write("<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>\n<root>\n");
            
            out.write(kategorieConfigList.getNazevXML()+"\n");
            
            Iterator iterator = kategorieConfigList.iterator();
            while(iterator.hasNext()){
                KategorieConfig kategorieConfig=(KategorieConfig)iterator.next();
                addXmlDataStKategorie(out, kategorieConfig);
            }
            
            out.write("</root>\n");
            out.close();
            
        } catch (IOException e) {
            System.err.println(ExceptionUtil.printStackTrace(e));
        }
        
    }
    
    /** udela kompletni xml soubor startovky jedne kategorie. kompletni v tomto pripade znamena, ze v nem jsou
     *  vsechny tagy (<?xml version=........> ... </xml>
     *  @param xmlFilename nazev vytvareneho xml souboru bez cesty (IoConfig.datapath) a bez extenze (.xml)
     *  @param config konfigurace kategorie - filtr, razeni startovnich subjektu ve startovce
     *  @param sl list vsech startovnich subjektu, je filtrovan a razen */
    public void doStartovkaXmlFileKategorie(String xmlFilename, KategorieConfigList kategorieConfigList, KategorieConfig kategorieConfig){
        try {
            BufferedWriter out= new BufferedWriter(new FileWriter(IoConfig.dataPath+xmlFilename+".xml"));
            out.write("<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>\n<root>\n");
            
            out.write(kategorieConfigList.getNazevXML()+"\n");
            
            addXmlDataStKategorie(out, kategorieConfig);
            
            out.write("</root>\n");
            out.close();
            
        } catch (IOException e) {
            System.err.println(ExceptionUtil.printStackTrace(e));
        }
    }
    
    /** prida do vystupniho proudu (BufferedWritter out) xml data jedne kategorie popsane v KategorieConfig, data se berou
     * z listu startovnich subjektu StartSubjektList, tento je filtrovan a razen na zaklade objektu KategorieConfig
     * @param out vystupni proud, do ktereho se zapisuji data
     * @param config konfigurace kategorie, udava ktere startovni subjekty budou v kategorii a jak budou setrideny
     * @param sl list vsech startovnich subjektu (i tech ktere nepatri ke kategorii), je filtrovan a razen podle KategorieConfig */
    public void addXmlDataStKategorie(BufferedWriter out, KategorieConfig kategorieConfig){
        StartSubjektList slVyfiltrovany;
        
        slVyfiltrovany = kategorieConfig.getFiltr().filtruj(getZavod().getSl());    //vyfiltruje sl podle startovniho filtru
        
        int jizda = kategorieConfig.getJizdaPoradi();               //podle ktere jizdy se budou radit startovni subjektu
        Collections.sort(slVyfiltrovany, new StartovniPoradiComparator(jizda));     //seradi StartSubjektList podle st.poradi
        
        try {
            out.write("<katg>\n");
            
            out.write(kategorieConfig.getKategorieXML()); //xml data o kategorii nazev, zkratka, barva cisel, atd...
            
            Iterator iterator = slVyfiltrovany.iterator();
            while (iterator.hasNext()){                             //pres vsechny startovni subjekty ve startovni kategorii
                StartSubjekt startSubjekt=(StartSubjekt)iterator.next();
                out.write(startSubjekt.toStartListXML());            //startovni data startovniho subjektu
            }
            
            out.write("</katg>\n");
            
        } catch (IOException e) {
            System.err.println(ExceptionUtil.printStackTrace(e));
        }
    }
    
    /** spusti pdf prohlizec a v nem pdf soubor
     *  @param filename jmeno pdf souboru bez extenze (.pdf) a bez cesty, ceta je dana konstantou IoConfig.dataPath */
    public void zobrazPDF(String filename){
        try {
            XML2PDF.ShowPDF(IoConfig.dataPath+filename+".pdf");
        } catch (Exception e) {
            System.err.println(ExceptionUtil.printStackTrace(e));
            System.exit(-1);
        }
    }
    
    /** provede transformaci xsl-fo xml souboru xmlFilename sablonou v souboru xslFilename. jmeno pdf souboru
     *  je odvozeno od xmlFilename pridanim extenze .pdf
     * @param xmlFilename jmeno souboru s xml daty bez extenze (.xml) a bez cesty
     * @param xslFilename jmeno souboru sablony pro xsl-fo transformaci bez extenze (.xsl) a bez cesty */
    public void convertXML2PDF(String xmlFilename, String xslFilename){
        try {                                                                           //xslt transformace
            XML2PDF.convertXML2PDF(new File(IoConfig.dataPath+xmlFilename+".xml"),
                    new File(IoConfig.dataPath+xslFilename+".xsl"),
                    new File(IoConfig.dataPath+xmlFilename+".pdf"));
            
            
        } catch (Exception e) {
            System.err.println(ExceptionUtil.printStackTrace(e));
            System.exit(-1);
        }
    }
    
    
    public Zavod getZavod() {
        return zavod;
    }
    
    public void setZavod(Zavod zavod) {
        this.zavod = zavod;
    }
    
    
}
